package com.modifiertech.lineage.handler;

import com.modifiertech.lineage.Lineage;
import com.modifiertech.lineage.api.PlayerData;
import com.modifiertech.lineage.api.PlayerDataLevelTag;
import com.modifiertech.lineage.base.ConfigHandler;
import com.modifiertech.lineage.commands.CmdHelper;
import com.modifiertech.lineage.event.PlayerDataHandler;
import com.modifiertech.lineage.event.PlayerExpModifyEvent;
import com.modifiertech.lineage.event.PlayerLevelUpEvent;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.monster.EntityMob;
import net.minecraft.entity.monster.IMob;
import net.minecraft.entity.passive.EntityAnimal;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.player.ItemFishedEvent;
import net.minecraftforge.event.world.BlockEvent;

import java.math.BigDecimal;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**用户升级处理器
 *
 */
public class PlayerLevelUpHandler {
    //饿汉
    public static PlayerLevelUpHandler INSTANCE=new PlayerLevelUpHandler();
    private PlayerLevelUpHandler(){
    }


    /**获取经验方法
     * 其中包含了升级/获取经验逻辑处理
     * 一般在玩家直接获取经验时，建议使用该方法
     * 系统或指令处理时可以直接调用底层的2个方法
     *
     * @param entityPlayer
     * @param exp
     */
    public void gainExp(EntityPlayer entityPlayer,double exp){
        if (exp<=0)return;
        PlayerData data = PlayerDataHandler.get(entityPlayer);
        //需分配的经验点数
        long expLeft=new BigDecimal(exp).longValue();
        //当前玩家等级（计算后）
        long currentLevel=data.getLevel();
        //当前玩家等级
        long oldLevel=data.getLevel();
        //当前玩家经验
        long currentExp=data.getCurrentExp();
        //是否升级
        boolean isLevelUp=false;

        while (expLeft>0){
            //当前玩家等级最大经验值
            long currentLevelMaxExp= PlayerDataLevelTag.getLevelMaxExp(currentLevel);
            //总经验达到升级标准
            if(expLeft+currentExp>=currentLevelMaxExp){
                //计算所升等级
                currentLevel++;
                expLeft-=(currentLevelMaxExp-currentExp);
                currentExp=0;
                isLevelUp=true;
            }else{
                expLeft=0;
                currentExp+=expLeft;
            }
        }
        //若升级触发升级事件,若不升级触发经验调整事件
        if(isLevelUp){
            levelUp(entityPlayer,oldLevel,currentLevel,currentExp,data);
        }else{
            expIncrease(entityPlayer, (long) exp,data);
        }
    }


    /**升级
     *
     * @param entityPlayer
     * @param oldLevel
     * @param currentLevel
     * @param currentExp
     * @param data
     */
    public void levelUp(EntityPlayer entityPlayer,long oldLevel,long currentLevel,long currentExp,PlayerData data){
        MinecraftForge.EVENT_BUS.post(new PlayerLevelUpEvent.Pre(entityPlayer,oldLevel,currentLevel,currentExp));
        boolean levelUpSuccess=false;
            //升级,获取升级状态
            levelUpSuccess=data.playerLevelUp(oldLevel,currentLevel,currentExp);
        //升级成功
        if(levelUpSuccess){
            //数据保存/同步
            data.saveAndSync();
            MinecraftForge.EVENT_BUS.post(new PlayerLevelUpEvent.Post(entityPlayer,oldLevel,currentLevel,currentExp));
            //升级失败
        }else{
            MinecraftForge.EVENT_BUS.post(new PlayerLevelUpEvent.PostErr(entityPlayer,oldLevel,currentLevel,currentExp));
        }
    }


    /**获取经验
     *
     * @param entityPlayer
     * @param currentExp
     * @param data
     */
    public void expIncrease(EntityPlayer entityPlayer,long currentExp,PlayerData data){
        MinecraftForge.EVENT_BUS.post(new PlayerExpModifyEvent.Pre(entityPlayer,currentExp));
        boolean expIncreaseSuccess=false;
            //属性添加
            expIncreaseSuccess=data.playerExpIncrease(currentExp);
        if(expIncreaseSuccess){
            //数据保存/同步
            data.saveAndSyncSilent();
            MinecraftForge.EVENT_BUS.post(new PlayerExpModifyEvent.Post(entityPlayer,currentExp));
        }else{
            MinecraftForge.EVENT_BUS.post(new PlayerExpModifyEvent.PostErr(entityPlayer,currentExp));
        }
    }





    /**计算击杀生物经验
     *
     * @param killingSource
     * @param beKilledMob
     * @return
     */
    public double calculateExpGainWhenKillingMobs(EntityPlayer killingSource, EntityLivingBase beKilledMob){
        float mobmaxhealth=beKilledMob.getMaxHealth();
        double expget=0d;
        //怪物击杀经验
        if(beKilledMob instanceof EntityMob){
            expget=new BigDecimal(mobmaxhealth* ConfigHandler.expRateFromKillingMob).setScale(0,BigDecimal.ROUND_UP).doubleValue();
        //动物击杀经验(整体收益的1/5)
        }else if(beKilledMob instanceof EntityAnimal){
            expget=new BigDecimal( mobmaxhealth* ConfigHandler.expRateFromKillingMob/5).setScale(0,BigDecimal.ROUND_UP).doubleValue();
        //玩家击杀经验
        }else if(beKilledMob instanceof EntityPlayer){
            expget=0d;
        //村民击杀经验(整体收益的1/3)
        }else if(beKilledMob instanceof EntityVillager){
            expget=new BigDecimal( mobmaxhealth* ConfigHandler.expRateFromKillingMob/3).setScale(0,BigDecimal.ROUND_UP).doubleValue();
        }
        //未定义的统一算一半收益。
        else{
            expget=new BigDecimal( mobmaxhealth* ConfigHandler.expRateFromKillingMob/2).setScale(0,BigDecimal.ROUND_UP).doubleValue();
        }
        return expget;
    }

    /**计算挖矿经验
     *
     * @return
     */
    public double calculateExpGainWhenBreakBlock(BlockEvent.BreakEvent event){
        IBlockState state = event.getState();
        Block block = state.getBlock();
        int expget = block.getExpDrop(state, event.getWorld(), event.getPos(), event.getExpToDrop());
        return expget;
    }
    /**计算钓鱼经验
     *
     * @return
     */
    public double calculateExpGainWhenFished(ItemFishedEvent event){
        int expget  = MathHelper.getInt(event.getEntityPlayer().getRNG(), 1, 6);
        return expget;
    }



}
